package net.oschina.dajiangnan.wx.process.pay.tools;

import net.oschina.dajiangnan.util.XStreamHelper;
import net.oschina.dajiangnan.wx.util.HttpTookit;
import net.oschina.dajiangnan.wx.util.HttpsTookit;
import net.oschina.dajiangnan.wx.util.RandomUtil;
import net.oschina.dajiangnan.wx.util.Signature;
import org.apache.log4j.Logger;

import net.oschina.dajiangnan.wx.constants.Config;
import net.oschina.dajiangnan.wx.process.pay.bean.RefundQueryResult;
import net.oschina.dajiangnan.wx.process.pay.bean.RefundResult;
import net.oschina.dajiangnan.wx.process.pay.xmlbean.RefundQueryReq;
import net.oschina.dajiangnan.wx.process.pay.xmlbean.RefundQueryResp;
import net.oschina.dajiangnan.wx.process.pay.xmlbean.RefundReq;
import net.oschina.dajiangnan.wx.process.pay.xmlbean.RefundResp;

public class Refund {
	
	// 退款URL
	private static final String REFUND_URL = "https://api.mch.weixin.qq.com/secapi/pay/refund";
	// 退款查询URL
	private static final String REFUND_QUERY_URL = "https://api.mch.weixin.qq.com/pay/refundquery";

	private static Logger logger = Logger.getLogger(Refund.class);

	/**
	 * 申请退款
	 * 
	 * @param transaction_id
	 *            微信订单号
	 * @param out_trade_no
	 *            商户订单号
	 * @param out_refund_no
	 *            商户退款单号,该单号自己定义，不重复的长字符串即可
	 * @param total_fee
	 *            总金额
	 * @param refund_fee
	 *            退款金额
	 * @param op_user_id
	 *            退款申请人
	 * @return RefundResult
	 */
	public static RefundResult refund(String transaction_id,
			String out_trade_no, String out_refund_no, int total_fee,
			int refund_fee, String op_user_id) {

		logger.info("Refund operation,request:{transaction_id:"
				+ transaction_id + ",out_trade_no:" + out_trade_no
				+ ",out_refund_no:" + out_refund_no + ",total_fee:" + total_fee
				+ ",refund_fee:" + refund_fee + ",op_user_id:" + op_user_id
				+ "}");

		RefundResult result = new RefundResult();

		if (refund_fee != total_fee) {
			result.setReturn_code("-1");
			result.setReturn_msg("The count of refund_fee and total_fee must be equal");
			logger.info("Refund operation,response:" + result.toString());
			return result;
		}
		RefundReq xml_req = new RefundReq();
		xml_req.setAppid(Config.appid);
		xml_req.setMch_id(Config.mch_id);
		xml_req.setNonce_str(RandomUtil.getRandomStr(32));
		xml_req.setOut_refund_no(out_refund_no);
		xml_req.setRefund_fee(String.valueOf(refund_fee));
		xml_req.setTotal_fee(String.valueOf(total_fee));
		if (transaction_id != null && transaction_id.length() > 0) {
			// transaction_id和out_trade_no二选一，优先使用transaction_id
			xml_req.setTransaction_id(transaction_id);
		} else {
			xml_req.setOut_trade_no(out_trade_no);
		}

		if (op_user_id == null || op_user_id.length() == 0) {
			op_user_id = Config.mch_id;
		}
		xml_req.setOp_user_id(op_user_id);

		try {
			xml_req.setSign(Signature.getSign(xml_req, null, Config.apikey));
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}

		String pkcs12FileName = Config.pkcs12FileName;
		String pics_pass = Config.pics_pass;
		String xml_resp = "";
		try {
			logger.debug("Request of refund:\r\n" + xml_req);
			xml_resp = new HttpsTookit(pkcs12FileName, pics_pass).doPost(
					REFUND_URL, xml_req.toString(),null,null,"UTF-8");
			logger.debug("Response of refund:\r\n" + xml_resp);
		} catch (Exception e) {
			logger.error(e);
			e.printStackTrace();
			result.setReturn_code("-1");
			result.setReturn_msg("Exception happened" + e);
			logger.info("Refund operation,response:" + result.toString());
			return result;
		}
		RefundResp resp = XStreamHelper.toBean(xml_resp, RefundResp.class);
		if (resp.getReturn_code().equals("SUCCESS")) {
			RefundResp rresp = XStreamHelper.toBean(xml_resp, RefundResp.class);
			result.setReturn_code(rresp.getReturn_code());
			result.setReturn_msg(rresp.getReturn_msg());
			result.setAppid(rresp.getAppid());
			result.setCash_fee(rresp.getCash_fee());
			result.setCash_refund_fee(rresp.getCash_refund_fee());
			result.setCoupon_refund_count(rresp.getCoupon_refund_count());
			result.setCoupon_refund_fee(rresp.getCash_refund_fee());
			result.setCoupon_refund_id(rresp.getCoupon_refund_id());
			result.setMch_id(rresp.getMch_id());
			result.setOut_refund_no(rresp.getOut_refund_no());
			result.setOut_trade_no(rresp.getOut_trade_no());
			result.setRefund_channel(rresp.getOut_trade_no());
			result.setRefund_fee(rresp.getRefund_fee());
			result.setRefund_id(rresp.getRefund_id());
			result.setTotal_fee(rresp.getTotal_fee());
			result.setTransaction_id(rresp.getTransaction_id());
		} else {
			result.setReturn_code(resp.getReturn_code());
			result.setReturn_msg(resp.getReturn_msg());
		}
		logger.info("Refund operation,response:" + result.toString());
		return result;
	}

	/**
	 * 退款查询 (特殊说明：transaction_id，out_trade_no，out_refund_no，refund_id四个参数四选一即可)
	 * https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_5
	 * 
	 * @param transaction_id
	 *            微信订单号
	 * @param out_trade_no
	 *            商户订单号
	 * @param out_refund_no
	 *            商户退款单号
	 * @param refund_id
	 *            微信退款单号
	 * @return RefundQueryResult
	 * 
	 */
	public static RefundQueryResult refundQuery(String transaction_id,
			String out_trade_no, String out_refund_no, String refund_id) {

		logger.info("RefundQuery, request params {transaction_id:"
				+ transaction_id + ",out_trade_no:" + out_trade_no
				+ ",out_refund_no:" + out_refund_no + ",refund_id:" + refund_id);
		RefundQueryResult result = new RefundQueryResult();

		RefundQueryReq xml_req = new RefundQueryReq();
		xml_req.setTransaction_id(transaction_id);
		xml_req.setOut_refund_no(out_refund_no);
		xml_req.setOut_trade_no(out_trade_no);
		xml_req.setRefund_id(refund_id);
		xml_req.setAppid(Config.appid);
		xml_req.setMch_id(Config.mch_id);
		xml_req.setNonce_str(RandomUtil.getRandomStr(32));
		try {
			xml_req.setSign(Signature.getSign(xml_req, null, Config.apikey));
		} catch (IllegalAccessException e) {
			e.printStackTrace();
			result.setResult_code("-1");
			result.setReturn_msg("Exception happened." + e);
			return result;
		}

		logger.debug("RefundQuery Request XML:\r\n" + xml_req.toString());
		String xml_resp = new HttpTookit().doPost(REFUND_QUERY_URL,
				xml_req.toString(),null,null,"UTF08");
		logger.debug("RefundQuery Response XML:\r\n" + xml_resp);
		RefundQueryResp obj_resp = XStreamHelper.toBean(xml_resp,
				RefundQueryResp.class);

		result.setReturn_code(obj_resp.getReturn_code());
		result.setReturn_msg(obj_resp.getReturn_msg());
		if (obj_resp.getReturn_code().equals("SUCCESS")) {
			result.setResult_code(obj_resp.getResult_code());
			result.setAppid(obj_resp.getAppid());
			result.setCash_fee(obj_resp.getCash_fee());
			result.setCoupon_refund_batch_id_0_0(obj_resp
					.getCoupon_refund_batch_id_0_0());
			result.setCoupon_refund_count_0(obj_resp.getCoupon_refund_count_0());
			result.setCoupon_refund_fee_0(obj_resp.getCoupon_refund_fee_0());
			result.setCoupon_refund_fee_0_0(obj_resp.getCoupon_refund_fee_0_0());
			result.setCoupon_refund_id_0_0(obj_resp.getCoupon_refund_id_0_0());
			result.setErr_code(obj_resp.getErr_code());
			result.setErr_code_des(obj_resp.getErr_code_des());
			result.setFee_type(obj_resp.getFee_type());
			result.setMch_id(obj_resp.getMch_id());
			result.setOut_refund_no_0(obj_resp.getOut_refund_no_0());
			result.setOut_trade_no(obj_resp.getOut_trade_no());
			result.setRefund_channel_0(obj_resp.getRefund_channel_0());
			result.setRefund_count(obj_resp.getRefund_count());
			result.setRefund_fee_0(obj_resp.getRefund_fee_0());
			result.setRefund_id_0(obj_resp.getRefund_id_0());
			result.setRefund_status_0(obj_resp.getRefund_status_0());
			result.setReturn_msg(obj_resp.getReturn_msg());
			result.setTotal_fee(obj_resp.getTotal_fee());
			result.setTransaction_id(obj_resp.getTransaction_id());
		}
		logger.info("RefundQuery, result:" + result.toString());
		return result;
	}
}
